#include <iostream>
#include <vector>
using namespace std;


namespace fuh
{
    template <class T>
    struct list_node//节点,虽然结构体有构造函数，但是继承了C语言的特点，结构体于结构体之外可以访问结构体成员
    {
        T _data;
        list_node<T> * _next;
        list_node<T> * _prev;
        list_node(const T& v = T())
        :_data(v)
        ,_next(nullptr)
        ,_prev(nullptr)
        {
            
        }
        list_node(T&& v)
        :_data(v)
        ,_next(nullptr)
        ,_prev(nullptr)
        {
            
        }
    };
    

    // // 直接实现版本的反向迭代器
    template <typename T>
    class list;//前置声明
    //在模板类A里面声明另外一个模板类B作为友元类，需要在该模板类A前面声明（如果B有定义在A后面的需求）或者定义模板类B才行,解决这个问题就前置声明
    //原因就是编译器找类的时候是自下而上的。

    template<typename  T, typename  Ref, typename  Ptr>
    struct __reverse_iterator//迭代器
    {
    public:
        friend class  list<T>;
        typedef list_node<T> Node;
        typedef __reverse_iterator<T, Ref, Ptr> self;
        __reverse_iterator() 
        :tmp(nullptr)
        {

        }
        __reverse_iterator(Node* val)
        :tmp(val)
        {

        }
        Ref operator*()
        {
            return tmp->_data;
        }
        Ptr operator->()const
        {
            return &(tmp->_data);
        }
        self& operator--()
        {
            tmp = tmp->_next;
            return *this;
        }
        self operator--(int)//后置
        {
            self t_iterator = *this;
            tmp = tmp->_next;
            return t_iterator;
        }
        self& operator++()
        {
            tmp = tmp->_prev;
            return *this;
        }
        self operator++(int)//后置
        {
            self t_iterator = *this;
            tmp = tmp->_prev;
            return t_iterator ;
        }
        bool operator!=(const self& it_2)
        {
            return tmp != it_2.tmp;
        }
        bool operator==(const self & it_2)
        {
            return tmp == it_2.tmp;
        }
        private:
        Node* tmp;
    };


    //利用正向迭代器实现的反向迭代器
    template <class iterator,class Ref, class Ptr>
    class ReverseIterator{
        public:
        typedef ReverseIterator<iterator,Ref,Ptr> self;
        ReverseIterator(iterator it):_it(it){}

        self& operator++(){
            _it--;
            return *this;
        }
        self& operator--(){
            _it++;
            return *this;
        }
        self operator++(int){
            self tmp = *this;
            _it--;
            return tmp;
        }
        self operator--(int){
            self tmp = *this;
            _it++;
            return tmp;
        }
        bool operator==(const self& rhs){
            return _it == rhs._it;
        }
        bool operator!=(const self& rhs){
            return _it != rhs._it;
        }
        Ref operator*(){
            return *_it;
        }
        Ptr operator->(){
            return _it.operator->();//这里不能直接调用·
        }
        private:
        iterator _it;
    } ;


    template<typename  T, typename  Ref, typename  Ptr>
    struct __list_iterator//迭代器
    {
    public:
         friend class  list<T>;//在模板类A里面声明另外一个模板类B作为友元类，需要在该模板类A前面声明（如果B有定义在A后面的需求）或者定义模板类B才行,解决这个问题就前置声明
        //原因就是编译器找类的时候是自下而上的。
        typedef list_node<T> Node;
        typedef __list_iterator<T, Ref, Ptr> self;
        __list_iterator() 
        :tmp(nullptr)
        {

        }
        __list_iterator(Node* val)
        :tmp(val)
        {

        }
        Ref operator*()
        {
            return tmp->_data;
        }
        Ptr operator->()const
        {
            return &(tmp->_data);
        }
        self& operator++()
        {
            tmp = tmp->_next;
            return *this;
        }
        self operator++(int)//后置
        {
            self t_iterator = *this;
            tmp = tmp->_next;
            return t_iterator;
        }
        self& operator--()
        {
            tmp = tmp->_prev;
            return *this;
        }
        self operator--(int)//后置
        {
            self t_iterator = *this;
            tmp = tmp->_prev;
            return t_iterator ;
        }
        bool operator!=(const self& it_2)
        {
            return tmp != it_2.tmp;
        }
        bool operator==(const self & it_2)
        {
            return tmp == it_2.tmp;
        }
        private:
        Node* tmp;
    };

    
    template <class T>
    class list
    {
        typedef list_node<T> Node;
        public:
            typedef __list_iterator<T, T&, T*> iterator;
		    typedef __list_iterator<T, const T&, const T*> const_iterator;  
            // typedef __reverse_iterator<T, T&, T*> reverse_iterator;
		    // typedef __reverse_iterator<T, const T&, const T*> const_reverse_iterator;
            typedef ReverseIterator<iterator, T&, T*> Reverse_iterator_byIterator;
            typedef ReverseIterator<const_iterator, const T&, const T*> const_Reverse_iterator_byIterator;

            iterator begin()
            {
                return _head->_next;//隐式类型转换
            }
            iterator end()
            {
                return _head;//隐式类型转换
            }
            const_iterator begin()const
            {
                return _head->_next;//隐式类型转换
            }
            const_iterator end()const
            {
                return _head;//隐式类型转换
            }


            Reverse_iterator_byIterator rbegin()
            {
                return Reverse_iterator_byIterator(--end());
            }
            Reverse_iterator_byIterator rend()
            {
                return Reverse_iterator_byIterator(end());
            }
            const_Reverse_iterator_byIterator rbegin() const
            {
                return const_Reverse_iterator_byIterator(--end());
            }
            const_Reverse_iterator_byIterator rend() const
            {
                return const_Reverse_iterator_byIterator(end());
            } 


            //注释上面的反向迭代器，可以使用下面的直接迭代器
            // reverse_iterator rbegin()
            // {
            //     return _head->_prev;//隐式类型转换
            // }
            // reverse_iterator rend()
            // {
            //     return _head;//隐式类型转换
            // }
            // const_reverse_iterator rbegin()const
            // {
            //     return _head->_prev;//隐式类型转换
            // }
            // const_reverse_iterator rend()const
            // {
            //     return _head;//隐式类型转换
            // }   

            list()
            {
                empty_list();
            }
        
            template <class InputIterator>
            list(InputIterator first, InputIterator last)
            {
                empty_list();
                insert(end(),first,last);
            }
            list(size_t n,const T& val = T())
            {
                empty_list();
                while(n--!=0)
                {
                    push_back(val);
                }
            }
            list(int n,const T& val = T())
            {
                empty_list();
                while(n--!=0)
                {
                    push_back(val);
                }
            }
            list(const list& val)
            {
                empty_list();
                insert(end(),val.begin(),val.end());
            }
            list(list&& val)
            {
                swap(val);
            }
            ~list()
            {
                clear();
                delete _head;
            }
            void swap(list & t)
            {
                Node* tt = t._head;
                t._head = _head;
                _head = tt;
            }
            void empty_list()
            {
                _head = new Node;
                _head->_next = _head;
                _head->_prev = _head;
            }
            list& operator=(const list& val)
            {
                clear();
                insert(end(),val.begin(),val.end());
                return *this;
            }
            list& operator=(list&& val)
            {
                swap(val);
                return *this;
            }
            void push_back(const T& val)
            {
                insert(end(),val);
            }
            void push_back(T&& val)
            {
                insert(end(),move(val));
            }
            void push_front(T&& val)
            {
                insert(begin(),move(val));
            }
            void push_front(const T& val)
            {
                insert(begin(),val);
            }
            void pop_front()
            {
                erase(begin());
            }
            void pop_end()
            {
                erase(end()--);
            }
            iterator insert(const iterator& pos,const T& val = T())
            {
                Node* prev = pos.tmp->_prev;
                Node* cur = pos.tmp;
                Node* newnode = new Node;
                newnode ->_data = val;
                newnode->_next = cur;
                newnode->_prev = prev;
                prev->_next = newnode;
                cur->_prev = newnode;
                _size++;
                return newnode;
            }
            iterator insert(const  iterator& pos,T&& val)
            {
                Node* prev = pos.tmp->_prev;
                Node* cur = pos.tmp;
                Node* newnode = new Node;
                newnode ->_data = val;
                newnode->_next = cur;
                newnode->_prev = prev;
                prev->_next = newnode;
                cur->_prev = newnode;
                _size++;
                return newnode;
            }
            template <class InputIterator>
            void insert (iterator position, InputIterator first, InputIterator last)
            {
                while(first != last)
                {
                    position = insert(position,*first++);
                    position++;
                }
            }
            iterator erase(iterator pos)
            {
                Node* tmp = pos.tmp;
                Node *prev = tmp->_prev;
                Node *next = tmp->_next;
                delete tmp;
                next->_prev = prev;
                prev->_next = next;
                _size--;
                return next;
            }
            void clear()
            {
                iterator it = begin();
                while(it != end())
                {
                    it = erase(it);
                }
            }
        private:
            Node* _head;
            size_t _size = 0;
    };
    template <typename Container>
    void print_Container(const Container & con)
    {
        typename Container::const_iterator it = con.begin();
        while(it!=con.end())
        {
            cout<< *it<<' ';
            it++;
        }
        cout<<endl;
    }

    void Test_1()
    {
        list<int> l1;
        l1.push_back(1);
        l1.push_back(2);
        l1.push_back(3);
        l1.push_back(4);
        auto it = l1.begin();
        l1.insert(it,10);
        for(auto test_int: l1)
        {
            cout<<test_int<<' ';
        }
        cout<<endl;
        l1.erase(l1.begin());
        for(auto test_int: l1)
        {
            cout<<test_int<<' ';
        }
        cout<<endl;
    
    }
    void Test_2()
    {
        list<int> l1;
        vector<int> a({2,3,4,5});
        l1.insert(l1.end(),a.begin(),a.end());
        list<int> l2;
        l2 = l1;
        list<int> l3(1,2);
        return ;
    }
    void Test_3()
    {
        list<string> l1(2,"2222");
        print_Container(l1);
    }
    void Test_4()
    {
        list<int> l1;
        l1.push_back(1);
        l1.push_back(2);
        l1.push_back(3);
        l1.push_back(4);
        auto it = l1.rbegin();
        while(it != l1.rend())
        {
            cout<<*it++<<' ';
        }
        cout<<endl;
    }
    void Test_5()
    {
        list<int> l1;
        l1.push_back(1);
        l1.push_back(2);
        l1.push_back(3);
        l1.push_back(4);
        list<int>::Reverse_iterator_byIterator  it = l1.rbegin();
        while(it != l1.rend())
        {
            cout<<*it++<<' ';
        }
        cout<<endl;
    }
    void Test_6()
    {
        list<int> l1;
        l1.push_back(1);
        l1.push_back(2);
        l1.push_back(3);
        l1.push_back(4);
        const list<int> &l2 = l1;
        list<int>::const_Reverse_iterator_byIterator it = l2.rbegin();
        while(it != l2.rend())
        {
            cout<<*it++<<' ';
        }
        cout<<endl;
    }
};

int main()
{
    fuh::Test_2();
    return 0;
}